#include <iostream> 
#include <sys/eventfd.h>  
#include <sys/epoll.h>
#include <functional>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <cassert>
#include <unistd.h>
#include "../source/Poller.hpp"
#include "../source/TimerWheel.hpp"

class EventLoop{
private:
    using Functor = std::function<void()>;
    std::thread::id _thread_id;//线程id
    int _event_fd;
    std::unique_ptr<Channel> _event_channel;
    Poller _poller; //事件监控
    std::vector<Functor> _tasks;
    std::mutex _mutex;// 保证线程安全
    TimerWheel _timer_wheel;//定时器模块
public:
    //执行线程池中所有的任务
    void RunAllTask(){
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.swap(functor);//拿到线程池中的任务
        }
    }
    for(auto &f : functor){
        f();
    }
    return;

    static int CreateEventFd(){
        int efd = eventfd(0,EFD_CLOEXEC|EFD_NONBLOCK);//
        if(efd<0){
            lg(Error,"CREATE EVENTFD FAILED!!");
            abort();
        }
        return efd;
    }

    void ReadEventfd(){
        uint64_t res = 0;
        int ret = read(_event_fd,&res,sizeof(res));//res表示_event_fd写入值之和
        if(ret<0){
            if(errno == EINTR || errno == EGAIN){ //  EAGAIN -- 
                //表⽰⽆数据可读
                return;
            }
            lg(Error,"READ EVENTFD FAILED!");
            abort();
        }
        return;
    }

    void WeakUpEventFd(){
        uint64_t val = 1;
        int ret = write(_event_fd,&val,sizeof(val));
        if(ret<0){
            if(errno == EINR){
                return;
            }
            lg(Error,"READ EVENTFD FAILED!");
            abort();
        }
        return ;
    }
public:
    Eventloop():_thread_id(std::this_thread::get_id()),
                _event_fd(CreateEventFd()),_event_channel(new Channel(this,_event_fd))
                ,_timer_wheel(this){
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
        _event_channel->EnableRead();
    }
    
    void Start(){
        while(1){
            //1.事件监控
            std::vector<Channel *> actives;
            _poller.Poll(&actives);
            //2.事件处理
            for(auto &channel:actives){
                channel-HandleEvent();
            }
            //3.执行任务
            RunAllTask();
        }
    }

    bool IsInLoop(){
        return { _thread_id == std::this_thread::get_id(); }
    }
    
    void AssertInLoop(){
        assert( _thread_id == std::this_thread::get_id() );
    }
    
    void RunInLoop(const Functor &cb){
        if(IsInLoop()){
            return cb();
        }
        return QueueInLoop(cb);
    }
    
    void QueueInLoop(const Functor &cb){
        {   
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(cb);
        }
        //可能没有事件就绪，导致epoll阻塞
        //给eventfd写入一个数据，eventfd就会触发可读事件
        WeakUpEventFd();
    }
    
    void UpdataEvent(Channel *channel){
        return _poller.UpdateEvent(channel);
    }

    void RemoveEvent(Channel *channel){
        return _poller.RemoveEvent(channel);
    }

    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb){
        return _timer_wheel.TimerAdd(id,delay, cb);
    }
    void TimeRefresh(uint64_t id){
        return _timer_wheel.TimerRefresh(id);
    }
    void TimerCancel(uint64_t id){
        return _timer_wheel.TimerCancel(id);
    }
    bool HasTimer(uint64_t id){
        return _timer_wheel.HasTimer(id);
    } 
};


class LoopThread{//一个reactor线程
private:
    std::mutex _mutex; //互斥锁
    std::condition_variable _cond; //条件变量
    EventLoop *_loop;   //EventLoop指针变量，这个对象需要在线程内实例化
    std::thread _thread; //EventLoop对应的线程

private:
 /*实例化 EventLoop 对象，唤醒_cond上有可能阻塞的线程，并且开始运⾏EventLoop模块的功能*/
    void ThreadEntry(){
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);//加锁
            _loop = &loop;
            _cond.notify_all();
        }        
        loop.Start();
    }
public:
    LoopThread():_loop(NULL),
    _thread(std::thread(&LoopThread::ThreadEntry,this)){}
    
    EventLoop *GetLoop(){
        EventLoop *loop = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); //加锁
            _cond.wait(lock,[&](){ return _loop !=NULL; });//1、条件不满足（_loop 为 NULL），自动解锁
            //。2、
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool{
private:
    int _thread_count;
    int _next_idx;
    EventLoop *_baseloop;
    std::vector<LoopThread*> _threads;
    std::vector<EventLoop*> _loops;
public:
    LoopThreadPool(EventLoop *baseloop):_thread_count(0),_next_idx(0)
            ,_baseloop(baseloop){}
    void SetThreadCount(int count) { _thread_count = count; }
    void Create(){
        if(_thread_count > 0 ){
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for(int i=0;i<=_thread_count;i++){
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
        return;
    }
    EventLoop *NextLoop(){
        if(_thread_count==0){ return _baseloop; }
        int _next_idx =( _next_idx + 1) % _thread_count;
        return _loops[_next_idx];
    }
};

int main(){
    EventLoop loop;
    LoopThreadPool pool(&loop);
    pool.SetThreadCount(4);
    pool.Create();
    loop.Start();
    return 0;
}